#include <QFile>
#include <QDebug>
#include <QHostAddress>
#include <QMessageBox>

#include "client.h"
#include "protocol.h"
#include "ui_client.h"
#include "index.h"

Client::Client(QWidget *parent): QWidget(parent), ui(new Ui::Client)
{
    ui->setupUi(this);
    rh = new ResHandler();
    loadConfig(); //加载配置
    connect(&m_tcpSocket, &QTcpSocket::connected, this, &Client::showConnect);
    connect(&m_tcpSocket, &QTcpSocket::readyRead, this, &Client::recvMsg);
    m_tcpSocket.connectToHost(QHostAddress(this->m_strIP), this->m_usPORT);

}

// 返回单例模式下的静态对象
Client &Client::getInstance()
{
    static Client instance;
    return instance;
}

// 发送消息
void Client::sendMsg(PDU *pdu)
{
    // 显示pdu内容
    qDebug() << "发送消息->"
             << "消息类型:" << pdu->uiMsgType
             << "PDU长度:" << pdu->uiPDULen
             << "消息长度:" << pdu->uiMsgLen
             << "PDU数据1:" << pdu->caData
             << "PDU数据2:" << pdu->caData + 32
             << "消息内容:" << pdu->caMsg;
    // 将pdu写如套接字（发送pdu）
    m_tcpSocket.write((char*)pdu, pdu->uiPDULen);
    free(pdu);
    pdu = NULL;
}

PDU *Client::readPDU()
{
    qDebug() << "recvMsg 接收消息的长度:" << m_tcpSocket.bytesAvailable();

    // 从套接字中读取协议总长度到uiPDULen
    uint uiPDULen = 0;
    m_tcpSocket.read((char*)&uiPDULen, sizeof(uint));

    // 计算协议消息长度到uiMsgLen
    uint uiMsgLen = uiPDULen - sizeof(PDU);
    PDU* pdu      = mkPDU(0, uiMsgLen)    ;
    m_tcpSocket.read((char*)pdu + sizeof(uint), uiPDULen - sizeof(uint)); // 读取除了总长度以外的剩余长度的内容

    qDebug() << "接收消息->"
             << "消息类型:" << pdu->uiMsgType
             << "PDU长度:" << pdu->uiPDULen
             << "消息长度:" << pdu->uiMsgLen
             << "PDU数据1:" << pdu->caData
             << "PDU数据2:" << pdu->caData + 32
             << "消息内容:" << pdu->caMsg;
    return pdu;
}

void Client::handleRes(PDU *pdu)
{
    rh->pdu = pdu;
    switch(pdu->uiMsgType){
    case ENUM_MSG_TYPE_REGIST_RESPOND:
    {
        rh->regist();
        break;
    }
    case ENUM_MSG_TYPE_LOGIN_RESPOND:
    {
        rh->login();
        break;
    }
    case ENUM_MSG_TYPE_FIND_USER_RESPOND:
    {
        rh->findUser();
        break;
    }
    case ENUM_MSG_TYPE_ONLINE_USER_RESPOND:
    {
        rh->onlineUser(m_strLoginName);
        break;
    }
    case ENUM_MSG_TYPE_ADD_FRIEND_RESPOND:
    {
        rh->addFriend();
        break;
    }
    case ENUM_MSG_TYPE_ADD_FRIEND_REQUEST:
    {
        rh->addFriendRequest();
        break;
    }
    case ENUM_MSG_TYPE_ADD_FRIEND_AGREE_RESPOND:
    {
        rh->addFriendAgree();
        break;
    }
    case ENUM_MSG_TYPE_ADD_FRIEND_AGREE_REQUEST:
    {
        rh->addFriendAgree();
        break;
    }
    case ENUM_MSG_TYPE_FLUSH_FRIEND_RESPOND:
    {
        rh->flushFriend();
        break;
    }
    case ENUM_MSG_TYPE_DELETE_FRIEND_RESPOND:
    {
        rh->delFriend();
        break;
    }
    case ENUM_MSG_TYPE_CHAT_RESPOND:
    {
        rh->chatRequest();
        break;
    }
    case ENUM_MSG_TYPE_MKDIR_RESPOND:
    {
        rh->mkDir();
        break;
    }
    default:
        break;
    }
}

QString Client::getRootPath()
{
    return m_strRootPath;
}

Client::~Client()
{
    delete rh;
    delete ui;
}

// 加载配置文件
void Client::loadConfig()
{
    QFile file(":/client.config");
    if(file.open(QIODevice::ReadOnly))
    {
        QByteArray  baData   = file.readAll();
        QString     strData  = QString(baData);
        QStringList strList  = strData.split("\r\n");
        m_strIP  = strList.at(0);
        m_usPORT = strList.at(1).toUShort();
        m_strRootPath = strList.at(2);
        file.close();
        qDebug() << "loadConfig ip:" << m_strIP << "port:" << m_usPORT << "m_strRootPath:" << m_strRootPath;
    }
    else
    {
        qDebug() << "打开配置失败";
    }
}

// 显示服务器连接情况
void Client::showConnect()
{
    qDebug() << "连接服务器成功";
}

// 接收消息
void Client::recvMsg()
{
    PDU* pdu = readPDU();
    handleRes(pdu);
    free(pdu);
    pdu = NULL;
}

void Client::on_regist_PB_clicked()
{
    QString strName = ui->name_LE->text();
    QString strPwd  = ui->pwd_LE ->text();

    PDU* pdu = mkPDU(ENUM_MSG_TYPE_REGIST_REQUEST, 0);

    memcpy(pdu->caData     , strName.toStdString().c_str(), 32);
    memcpy(pdu->caData + 32, strPwd .toStdString().c_str(), 32);

    sendMsg(pdu);
}

void Client::on_login_PB_clicked()
{
    QString strName = ui->name_LE->text();
    QString strPwd  = ui->pwd_LE ->text();

    m_strLoginName = strName;

    PDU* pdu = mkPDU(ENUM_MSG_TYPE_LOGIN_REQUEST, 0);

    memcpy(pdu->caData     , strName.toStdString().c_str(), 32);
    memcpy(pdu->caData + 32, strPwd .toStdString().c_str(), 32);

    sendMsg(pdu);
}
